﻿using de.wolfmarco.pas.Shared.Cryptography;
using de.wolfmarco.pas.Shared.Database;
using de.wolfmarco.pas.Shared.MessageBoxes;
using Microsoft.Practices.Prism.Commands;
using MySql.Data.MySqlClient;
using System;
using System.ComponentModel;
using System.Configuration;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Windows;

namespace de.wolfmarco.pas.Shared.Properties
{
    public sealed partial class Settings
    {
        public Settings()
        {
            protectedString = new ProtectedString();

            if (NeedsUpgrade)
            {
                Upgrade();
                NeedsUpgrade = false;
                Save();
            }

            SaveCommand = new DelegateCommand<object>(OnTrySave, CanSave);

            PropertyChanged += DbSettings_PropertyChanged;
        }

        #region ProtectedString

        private ProtectedString protectedString;

        public override object this[string propertyName]
        {
            get
            {
                switch (propertyName)
                {
                    case "Password":
                        protectedString.Value = base[propertyName] as String;
                        return protectedString.UnProtect();
                    default:
                        return base[propertyName];
                }
            }
            set
            {
                switch (propertyName)
                {
                    case "Password":
                        protectedString.Value = value as String;
                        base[propertyName] = protectedString.Protect();
                        break;
                    default:
                        base[propertyName] = value;
                        break;
                }
            }
        }

        #endregion ProtectedString

        #region DbConnection

        public DbConnection DbConnection
        {
            get
            {
                DbConnection connection;

                switch (DatabaseType)
                {
                    case DatabaseTypeEnum.MySQL:
                        connection = CreateMySqlConnection();
                        break;
                    case DatabaseTypeEnum.Local:
                    default:
                        connection = CreateLocalDbConnection();
                        break;
                }

                return connection;
            }
        }

        public DbConnection CreateLocalDbConnection()
        {
            StringBuilder attachDbFileName = new StringBuilder();

            attachDbFileName.Append(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));

            attachDbFileName.Append(@"\");
            FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location);
            attachDbFileName.Append(versionInfo.CompanyName);

            attachDbFileName.Append(@"\Database.mdf");

            string dbFileName = attachDbFileName.ToString();

            DbConnectionStringBuilder connectionString = new DbConnectionStringBuilder();
            connectionString.Add("Data Source", @"(LocalDB)\v11.0");
            connectionString.Add("AttachDbFileName", dbFileName);
            connectionString.Add("Integrated Security", true);

            return new SqlConnection(connectionString.ToString());
        }

        public DbConnection CreateMySqlConnection()
        {
            DbConnectionStringBuilder connectionString = new DbConnectionStringBuilder();
            connectionString.Add("Server", Server);
            connectionString.Add("Port", Port);
            connectionString.Add("Database", DatabaseName);
            connectionString.Add("Uid", UserName);
            connectionString.Add("Pwd", Password);
            connectionString.Add("UseCompression", true);

            return new MySqlConnection(connectionString.ToString());
        }

        #endregion DbConnection

        #region Save & PropertyChanged

        private void DbSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            isDirty = true;

            if (SaveCommand != null)
                SaveCommand.RaiseCanExecuteChanged();
        }

        private bool isDirty = false;

        public override void Save()
        {
            base.Save();

            isDirty = false;
            if (SaveCommand != null)
                SaveCommand.RaiseCanExecuteChanged();
        }

        public DelegateCommand<object> SaveCommand { get; private set; }

        private void OnTrySave(object arg)
        {
            try
            {
                OnSave(arg);
            }
            catch (Exception ex)
            {
                PASMessageBox.ShowException(ex);
            }
        }

        private void OnSave(object arg)
        {
            Save();
        }

        private bool CanSave(object arg)
        {
            return isDirty;
        }

        #endregion Save & PropertyChanged
    }
}
